package in.ac.iiitd.cse201.Devansh2011042.finallabexam;

import in.ac.iiitd.cse201.Devansh2011042.finallabexam.DiskPage;
import in.ac.iiitd.cse201.Devansh2011042.finallabexam.Page;
import java.util.HashMap;
import java.util.Random;

/**
 * Simulate a partition as a repository of Pages, each of which can be addressed
 * by a integer (e.g., offset from the start of the partition). For simplicity
 * we allow only one instance of the partition -- ensured through the factory
 * pattern.
 *
 * @author bedathur
 */
public class PageFactory {

    /**
     * Encapsulates the Page and its address.
     */
    public final class PagePair {

        public Integer address;
        public Page page;
    }
    /**
     * Maintains a list of formatted pages in the partition indexed by their
     * address for quick retrieval.
     */
    private HashMap<Integer, Page> allPages;
    /**
     * Singleton instance of the PageFactory.
     */
    private static PageFactory pf = null;

    /**
     * Private constructor, which is accessed only through the static methods of
     * the same class. By default, it creates a partition of 10k pages and fills
     * them with random content.
     */
    private PageFactory() {
        allPages = new HashMap<Integer, Page>(10000);
        Random rand = new Random();
        for (int i = 0; i < 10000; i++) {
            Page p = new DiskPage(new Double(rand.nextGaussian()).toString());
            allPages.put(i, p);
        }
    }

    /**
     * Public static method that provides the Factory pattern to ensure
     * singleton instance of the partition.
     *
     * @return
     */
    public static synchronized PageFactory getPageFactory() {
        if (pf == null) {
            pf = new PageFactory();
        }
        return pf;
    }

    /**
     * For a given address, return the page along with its address.
     *
     * @param k
     * @return
     */
    public PagePair getPage(int k) {
        PagePair pp = new PagePair();

        pp.address = k;
        pp.page = allPages.get(k);
        return pp;
    }

    /**
     * Return a random page and its address from the available pages in the
     * partition.
     *
     * @return
     */
    public PagePair getRandomPage() {
        Random rand = new Random();
        int k = rand.nextInt(10000);
        return getPage(k);
    }
}
